{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 总任务\n",
    "针对“发票样例”中的以压缩文件形式存放的发票文件\\\n",
    "\n",
    "1 通过python 解压成单独的pdf文件格式的电子发票文件\\\n",
    "2 读取pdf文件中的信息，在mysql数据库中建立相应的数据表，将读取的信息存入数据表中\\\n",
    "3 建立web服务器，连接第2步得到的mysql数据库，为用户提供发票的查询服务与下载服务，将满足查询条件的多张发票打包下载\\\n",
    "4 批量打印满足查询条件的多张发票\n",
    "\n",
    "### (1) web服务器设想\n",
    "整体采用前后端分离的架构（VUE + Flask + MySQL）。\n",
    "前端服务和后端服务之间使用JSON格式的数据进行交互。\n",
    "\n",
    "##### 后端\n",
    "Flask实现简单接口和路由，完成和数据库的交互。\n",
    "- /:主页面\n",
    "- /search: 查询\n",
    "- /download: 下载，多发票打包下载\n",
    "单个文件可以直接发送，批量文件的话需要对多个文件进行打包后再发送。\n",
    "\n",
    "##### 前端\n",
    "使用Vue框架进行开发，使用element UI做组件渲染。\n",
    "使用axios插件发送HTTP请求（GET,POST）。\n",
    "实现简单的文件下载功能。\n",
    "\n",
    "### （2）Flask 后端框架\n",
    "flask是一个非常轻量化的后端框架，与django相比，它拥有更加简洁的框架。django功能全而强大，它内置了很多库包括路由，表单，模板，基本数据库管理等。flask框架只包含了两个核心库（Jinja2 模板引擎和 Werkzeug WSGI 工具集），需要什么库只需要外部引入即可，让开发者更随心所欲的开发应用。\n",
    "\n",
    "使用之前需要先**安装Flask库**：```pip install flask```\n",
    "\n",
    "flask项目**快速构建**，似乎只有pycharm企业版能够自动帮你构建项目，其他编程软件只能通过手动创建。因为flask框架对项目目录没有要求，所以项目的目录我们可以根据自己的需求设计，即使是单个文件也可以执行。\n",
    "\n",
    "在项目根目录下构建：\n",
    "- webapp包目录，存放flask代码，包内有__init__.py文件\n",
    "- templates目录，存放模板文件\n",
    "- static目录，存放js,css等静态文件。其下建立js目录，放入jquery、echarts的js文\n",
    "- app.py入口文件\n",
    "\n",
    "使用```pip freeze >requirements.txt```可以记录所有依赖包和精确的版本号，以便在新环境中进行操作部署。\n",
    "\n",
    "使用```pip install -r requirements.txt```可以在新的环境中安装所有依赖包。\n",
    "\n",
    "快速入门传送门：https://www.bilibili.com/video/BV17W41177oE?p=1&vd_source=9e5b81656aa2144357f0dca1094e9cbe\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app \"__main__\" (lazy loading)\n",
      " * Environment: production\n",
      "   WARNING: Do not use the development server in a production environment.\n",
      "   Use a production WSGI server instead.\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n",
      "127.0.0.1 - - [07/Oct/2022 10:14:28] \"\u001b[37mGET / HTTP/1.1\u001b[0m\" 200 -\n"
     ]
    }
   ],
   "source": [
    "# 下面就是Flask启动一个后端服务的主要逻辑了，简单的7行代码\n",
    "# -*- coding:utf-8 -*-\n",
    "\n",
    "# 1.导入flask扩展\n",
    "from flask import Flask \n",
    "\n",
    "# 2.创建flask应用程序实例\n",
    "# 需要传入__name__,作用是为了确定资源所在的路径\n",
    "app = Flask(__name__)\n",
    "# app.config['ENV'] = \"development\"\n",
    "\n",
    "# 3. 定义路由和视图函数\n",
    "# Flask中定义路由是通过装饰器实现的\n",
    "@app.route('/',methods=[\"GET\",\"POST\"])\n",
    "def index():\n",
    "    return '你好 Flask!'\n",
    "\n",
    "# 4. 启动服务\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"name\": \"\\u5f20\\u4e09\", \"age\": \"18\"}\n",
      "{'name': '张三', 'age': '18'}\n"
     ]
    }
   ],
   "source": [
    "# python 将数据封装成JSON\n",
    "import json\n",
    "\n",
    "dict = {\n",
    "    \"name\":\"张三\",\n",
    "    \"age\":\"18\"\n",
    "}\n",
    "\n",
    "# 编码 \n",
    "str_json = json.dumps(dict)\n",
    "print(str_json)\n",
    "\n",
    "# 解码\n",
    "dict2 = json.loads(str_json)\n",
    "print(dict2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 打包文件\n",
    "import zipfile \n",
    "import os \n",
    "import time\n",
    "from time import sleep\n",
    "import shutil\n",
    "import random\n",
    "\n",
    "# 压缩文件\n",
    "filelist = [\"../发票样例/20201223_通行费电子发票_2张/invoice/91510000709155317M_44308ed89a5c467e9ede236eb1efd8bc.pdf\",\"../发票样例/20201223_通行费电子发票_3张/invoice/91510000689919120D_f3c17dea5202450daa1d6b293390644c.pdf\"]\n",
    "# 先将不同目录下的文件复制到./temp下\n",
    "time = str(int(time.time())+random.randint(0,100000))# 防止冲突，因为有可能有人同时下载文件\n",
    "os.mkdir(\"./temp/\"+time)\n",
    "des_path = \"./temp/\"+time+\"/\"\n",
    "zip = zipfile.ZipFile(des_path+\"/test.zip\",\"w\",zipfile.ZIP_DEFLATED)\n",
    "# 将指定文件复制到临时文件夹下\n",
    "for i,file_path in enumerate(filelist):\n",
    "    path = des_path + str(i) + \".pdf\"\n",
    "    f = open(path,\"wb\")\n",
    "    src_file = open(file_path,\"rb\")\n",
    "    f.write(src_file.read())\n",
    "    f.close()\n",
    "    src_file.close()\n",
    "# 压缩批量文件\n",
    "for file in os.listdir(des_path):\n",
    "    if file.endswith('.pdf'):\n",
    "        zip.write(des_path+file) \n",
    "zip.close()\n",
    "sleep(3) # 等待发送\n",
    "shutil.rmtree(des_path) # 发送成功之后需要删除该文件夹"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.0 ('base')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "d2ac46498bf9d36d8c53ef3ef5f1114d28cdeda33c2544899d6ce51d38e12b9d"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
